//------------------------------------------------------------------------------
// X2D Game Engine
// Copyright (C) 2006-2007 Janusz Kowalski
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------

#ifndef X2D_EXT_HEADER
#define X2D_EXT_HEADER 1

#include "SDL.h"
#include <cstring>
#include <string>
#include <stdexcept>

#include "Box2D.h"

#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
namespace fs = boost::filesystem;

//#define ASSURE(cond) if(!(cond)) throw __FILE__ ": condition (" #cond ") false!"

namespace x2d {

inline Uint32 endian_swap(Uint32 value) {
  return SDL_Swap32(value);
}

inline Uint16 endian_swap(Uint16 value) {
  return SDL_Swap16(value);
}

inline Uint8 endian_swap(Uint8 value) {
  return value;
}

inline Sint8 endian_swap(Sint8 value) {
  return value;
}

inline Sint32 endian_swap(Sint32 value) {
  return SDL_Swap32(value);
}

inline float32 endian_swap(float32 value) {
  Uint32 *ptr = reinterpret_cast<Uint32*>(&value);
  *ptr=SDL_Swap32(*ptr);
  return value;
}

// T should be: Sint8, Uint8, Sint16, Uint16, Sint32, Uint32
template <class T> void net_read(fs::ifstream &stream, T &value) {
  stream.read(reinterpret_cast<char*>(&value),sizeof(value));
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
  value=endian_swap(value);
#endif
}

// T should be: Sint8, Uint8, Sint16, Uint16, Sint32, Uint32
template <class T> T net_read(fs::ifstream &stream) {
  T value;
  stream.read(reinterpret_cast<char*>(&value),sizeof(value));
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
  return endian_swap(value);
#else
  return value;
#endif
}

template <class T> void net_write(fs::ofstream &stream, T value) {
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
  value = endian_swap(value);
#endif
  stream.write(reinterpret_cast<char*>(&value),sizeof(value));
}
  
inline static int floorDiv(int a, int b) {
  int q = a/b;
  if(a-q*b<0) q-=1;
  return q;
}

inline static int ceilDiv(int a, int b) {
  int q=a/b;
  if((q*b)<a) q+=1;
  return q;
}



// Read line from the given stream.
// RETURN VALUE
//   true - Success.
//   false - Line is too long. Only (size - 1) bytes was read.
bool readLine(FILE *stream, char *buffer, int size);

// Jezeli ktos nie obsluzy EOF, i bedzie ciagle czytal za plikiem
// to oznacza to blad.

// Inicjacja x2d i jego bibliotek
void init(int argc, char *argv[]);
  
// Funkcja zwraca list�plik� w danym katalogu
// opr�z tych zaczynajcych si�od kropki
// Dane s w postaci listy wskanik�, zako�zonej 0
// Lista jest alokowana automatycznie, i musi zosta�zwolniona
char *dir_list(const char *path);
void logHardwareInfo();

}

#ifndef MSVC
template <class T> inline T max(T a, T b) { return a>b?a:b; }

template <class T> inline T min(T a, T b) { return a<b?a:b; }
#endif

#endif
